package org.net5ijy.commons.http;

import static org.net5ijy.commons.http.constants.CharsetNames.CHARSET_UTF8;
import static org.net5ijy.commons.http.constants.HttpHeaderNames.HEADER_NAME_CONTENT_LENGTH;
import static org.net5ijy.commons.http.constants.UrlParameterConstants.URL_PARAM_STARTER;

import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.net5ijy.commons.http.response.ResponseHolder;
import org.net5ijy.commons.http.test.ProgressBar;
import org.net5ijy.commons.util.StringUtil;

/**
 * 封装一些共用的Http请求方法
 *
 * @author xuguofeng
 * @date 2020/7/14 9:03
 */
@Slf4j
@Data
public abstract class AbstractHttp implements Http {

  protected Proxy proxy;

  protected String proxyName;

  protected String proxyPassword;

  public AbstractHttp() {
  }

  public AbstractHttp(Proxy proxy, String proxyName, String proxyPassword) {
    this.proxy = proxy;
    this.proxyName = proxyName;
    this.proxyPassword = proxyPassword;
  }

  public AbstractHttp(String proxyHost, int proxyPort, String proxyName, String proxyPassword) {
    this.proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
    this.proxyName = proxyName;
    this.proxyPassword = proxyPassword;
  }

  protected String getRequestParameterString(
      String url, Map<String, String> params) throws IOException {

    // 请求参数
    String paramStr = "";

    if (params != null && !params.isEmpty()) {

      paramStr = url.contains(URL_PARAM_STARTER) ? "&" : "?";

      List<NameValuePair> paramsList = new ArrayList<>();

      for (Entry<String, String> e : params.entrySet()) {
        paramsList.add(new BasicNameValuePair(e.getKey(), e.getValue()));
      }

      paramStr =
          paramStr + EntityUtils.toString(new UrlEncodedFormEntity(paramsList, CHARSET_UTF8));
    }
    return paramStr;
  }

  protected String appendUrlArgument(String url, String arg, String val) {

    if (StringUtil.isNullOrEmpty(url)) {
      return url;
    }

    StringBuilder sb = new StringBuilder(url);

    if (url.contains(URL_PARAM_STARTER)) {
      sb.append("&");
      sb.append(arg);
      sb.append("=");
      sb.append(val);
      return sb.toString();
    }

    sb.append("?");
    sb.append(arg);
    sb.append("=");
    sb.append(val);
    return sb.toString();
  }

  protected <T> T parseJson(String json, Class<T> type) {
    ObjectMapper mapper = new ObjectMapper();
    try {
      return mapper.readValue(json, type);
    } catch (IOException e) {
      log.error(e.getMessage(), e);
      throw new RuntimeException(e);
    }
  }

  protected void printProgress(long total, long current, boolean last) {
    ProgressBar progressBar = ProgressBar.getProgressBar();
    if (total == 0) {
      progressBar.printProgressWithoutPercentage();
    } else {
      Double progress = current * 100.0 / total;
      progressBar.printProgress(progress.intValue());
    }
    if (last) {
      System.out.println();
    }
  }

  protected long getContentLength(ResponseHolder response) {
    String contentLength = response.headerValue(HEADER_NAME_CONTENT_LENGTH);
    if (contentLength != null) {
      return Integer.parseInt(contentLength);
    }
    return 0;
  }

  protected String chars(int length, char ch) {
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < length; i++) {
      builder.append(ch);
    }
    return builder.toString();
  }
}
